package com.hzncc.flowable_diboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diboot.core.binding.Binder;
import com.diboot.core.holder.ThreadLocalHolder;
import com.diboot.core.util.BeanUtils;
import com.diboot.core.util.S;
import com.hzncc.flowable_diboot.contract.entity.SalesContract;
import com.hzncc.flowable_diboot.contract.service.SalesContractService;
import com.hzncc.flowable_diboot.contract.vo.SalesContractListVO;
import com.hzncc.flowable_diboot.dto.ScreenDto;
import com.hzncc.flowable_diboot.entity.Business;
import com.hzncc.flowable_diboot.entity.Customer;
import com.hzncc.flowable_diboot.entity.OppoFlowOrder;
import com.hzncc.flowable_diboot.entity.RegionalCoordinates;
import com.hzncc.flowable_diboot.mapper.CustomerMapper;
import com.hzncc.flowable_diboot.mapper.OppoFlowOrderMapper;
import com.hzncc.flowable_diboot.mapper.RegionalCoordinatesMapper;
import com.hzncc.flowable_diboot.service.BusinessService;
import com.hzncc.flowable_diboot.service.ScreenDataService;
import com.hzncc.flowable_diboot.util.ConstantUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ScreenDataServiceImpl implements ScreenDataService {
    private final BusinessService businessService;
    private final CustomerMapper customerMapper;
    private final OppoFlowOrderMapper oppoFlowOrderMapper;
    private final RegionalCoordinatesMapper regionalCoordinatesMapper;
    private final CacheManager cacheManager;
    private final SalesContractService salesContractService;

    /**
     * 查询赢单客户
     *
     * @param dto 查询参数
     * @return
     * @author 陈广煜
     * @date 2024-08-02
     */
    public Long getWinCustomer(ScreenDto dto) {
        // 查询时间范围内赢单的流程单
        QueryWrapper<OppoFlowOrder> qw = new QueryWrapper<>();
        qw.lambda().select(OppoFlowOrder::getId)
                .eq(OppoFlowOrder::getResult, ConstantUtil.WIN_Result)
                .ne(OppoFlowOrder::getUpdateTime, dto.getEndDate())
                .le(OppoFlowOrder::getUpdateTime, dto.getStartDate());
        List<OppoFlowOrder> oppoFlowOrders = oppoFlowOrderMapper.selectList(qw);
        List<String> orderIds = BeanUtils.collectToList(oppoFlowOrders, OppoFlowOrder::getId);
        if (orderIds.isEmpty()) {
            return 0L;
        }
        // 查询事业部下的赢单客户
        QueryWrapper<Business> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(Business::getId, Business::getCustomerId).eq(Business::getStage, ConstantUtil.WIN_STAGE);
        queryWrapper.lambda().eq(Business::getTenantId, dto.getTenantId())
                .eq(Business::getStatus, ConstantUtil.FLOW_TYPE_OVER)
                .eq(Business::getUid, dto.getUserId())
                .eq(Business::getOfficeId, dto.getOfficeId()).in(Business::getOrderId, orderIds);
        List<Business> bus = businessService.getEntityList(queryWrapper);
        List<String> list = BeanUtils.collectToList(bus, Business::getCustomerId);
        if (list.isEmpty()) {
            return 0L;
        }
        QueryWrapper<Customer> cunt = new QueryWrapper<>();
        cunt.lambda().in(Customer::getId, list);
        Long size = customerMapper.selectCount(cunt);
        return size;
    }

    /**
     * 查询客户分布
     *
     * @param dto 查询参数
     * @return
     * @author 陈广煜
     * @date 2024-08-02
     */
    @Override
    public Object customerDistribution(ScreenDto dto) {
        String tenantId = dto.getTenantId();
        QueryWrapper<Customer> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(Customer::getCity, Customer::getName)
                .eq(Customer::getIsEnter, 1);
        if (S.isNotBlank(tenantId)) {
            queryWrapper.lambda().eq(Customer::getTenantId, tenantId);
        }
        if (S.isNotBlank(dto.getUserId())) {
            queryWrapper.lambda().eq(Customer::getPrincipal, dto.getUserId());
        }
        // 查询客户 按城市分类统计客户分布
        ThreadLocalHolder.setIgnoreInterceptor();
        List<Customer> customers = customerMapper.selectList(queryWrapper);
        customers = customers.stream().distinct().collect(Collectors.toList());
        List<Customer> notNullCity = customers.stream().filter(c -> c.getCity() != null).collect(Collectors.toList());
        Map<String, List<Customer>> groupByCity = notNullCity.stream().collect(Collectors.groupingBy(Customer::getCity));
        List<Map<String, Object>> resList = new ArrayList<>();
        for (Map.Entry<String, List<Customer>> entry : groupByCity.entrySet()) {
            //res.put(entry.getKey(), entry.getValue().size());
            Map<String, Object> res = new HashMap<>();
            res.put("name", entry.getKey());
            res.put("value", entry.getValue().size());
            res.put("coord", searchCityCoordinates(entry.getKey()));
            resList.add(res);
        }
        return resList;
    }

    /**
     * 查询省市区坐标
     *
     * @param area 地区
     * @return
     * @author 陈广煜
     * @date 2024-08-06
     */
    //@Cacheable(value = ConstantUtil.CACHE_AREA, key = "#area")
    public RegionalCoordinates searchAreaCoordinates(String area) {
        Cache cache = cacheManager.getCache(ConstantUtil.CACHE_AREA);
        RegionalCoordinates regionalCoordinates = cache.get(area, RegionalCoordinates.class);
        if (regionalCoordinates != null) {
            return regionalCoordinates;
        }
        QueryWrapper<RegionalCoordinates> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(RegionalCoordinates::getLat, RegionalCoordinates::getLng).eq(RegionalCoordinates::getArea, area);
        RegionalCoordinates reg = regionalCoordinatesMapper.selectOne(queryWrapper);
        cache.put(area, reg);
        return reg;
    }

    /**
     * 查询市坐标
     *
     * @param city 城市名
     * @return
     * @author 陈广煜
     * @date 2024-08-06
     */
    //@Cacheable(value = ConstantUtil.CACHE_CITY, key = "#city")
    public RegionalCoordinates searchCityCoordinates(String city) {
        Cache cache = cacheManager.getCache(ConstantUtil.CACHE_CITY);
        RegionalCoordinates regionalCoordinates = cache.get(city, RegionalCoordinates.class);
        if (regionalCoordinates != null) {
            return regionalCoordinates;
        }
        QueryWrapper<RegionalCoordinates> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().select(RegionalCoordinates::getLat, RegionalCoordinates::getLng)
                .and(w -> {
                    w.eq(RegionalCoordinates::getCity, city).isNull(RegionalCoordinates::getArea);
                })
                .or(w -> {
                    w.eq(RegionalCoordinates::getCity, ConstantUtil.MUNICIPAL_DISTRICT)
                            .isNull(RegionalCoordinates::getArea)
                            .eq(RegionalCoordinates::getProvince, city);
                });
        RegionalCoordinates reg = regionalCoordinatesMapper.selectOne(queryWrapper);
        cache.put(city, reg);
        return reg;
    }

    /**
     * 销售排行
     *
     * @param dto 查询参数
     * @return
     */
    @Override
    public Object salesRanking(ScreenDto dto) {
        String tenantId = dto.getTenantId();
        QueryWrapper<SalesContract> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SalesContract::getTenantId, tenantId)
                .eq(SalesContract::getPushStatus, 1) // 推送成功
                .between(SalesContract::getCreateTime, dto.getStartDate(), dto.getEndDate());
        List<SalesContract> entityList = salesContractService.getEntityList(queryWrapper);
        if (entityList == null || entityList.isEmpty()) {
            return Collections.emptyList();
        }
        List<SalesContractListVO> salesContractListVOS = Binder.convertAndBindRelations(entityList, SalesContractListVO.class);
        List<Map<String,Object>> resList = new ArrayList<>();
        salesContractListVOS.stream().filter(el -> el.getSalesEmployeeLabel() != null).collect(Collectors.groupingBy(SalesContractListVO::getSalesEmployeeLabel))
                .forEach((k, v) -> {
                    Map<String, Object> res = new HashMap<>();
                    res.put("name", k); // 销售员
                    res.put("total", v.stream().map(c -> new BigDecimal(c.getFixedDiscountAmount())).reduce(BigDecimal.ZERO,BigDecimal::add)); // 销售额
                    res.put("count", v.size()); // 签订数量
                    resList.add(res);
                });
        return resList.stream().sorted((m,b) -> ((BigDecimal)b.get("total")).compareTo((BigDecimal) m.get("total"))).collect(Collectors.toList());
    }

}
